package com.blue.scheduled.logs.aop;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.blue.common.constant.CommonConstant;
import com.blue.po.job.JobLogsPO;
import com.blue.po.job.ScheduledJobPO;
import com.blue.service.job.IJobLogsService;
import com.blue.service.job.IScheduledJobService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.UUID;

/**
 * @author nanjie.chen
 * Created on 2023/10/4
 */
@Component
@Aspect
public class JobLogAop {
    @Autowired
    private IJobLogsService jobLogsService;

    @Autowired
    private IScheduledJobService scheduledJobService;

    @Pointcut("@annotation(com.blue.scheduled.logs.annotation.JobLog)")
    public void pointCut() {
    }

    @Around("pointCut()")
    public Object jobLog(ProceedingJoinPoint proceedingJoinPoint) {
        //设置traceId
        String tid = UUID.randomUUID().toString().replace("-", "");
        MDC.put("traceId", tid);
        //记录日志
        String className = proceedingJoinPoint.getTarget().getClass().getName();
        ScheduledJobPO scheduledJobPO = scheduledJobService.getOne(new LambdaQueryWrapper<ScheduledJobPO>()
                .eq(ScheduledJobPO::getClassName, className));
        JobLogsPO jobLogsPO = new JobLogsPO();
        jobLogsPO.setTraceId(tid);
        jobLogsPO.setClassName(className);
        jobLogsPO.setRemark(scheduledJobPO.getRemark());
        jobLogsPO.setStatus(CommonConstant.RUNNING);
        jobLogsService.save(jobLogsPO);
        try {
            Object result = proceedingJoinPoint.proceed();
            //执行完毕更新状态为成功
            jobLogsPO.setStatus(CommonConstant.SUCCESS);
            jobLogsService.updateById(jobLogsPO);
            return result;

        } catch (Throwable throwable) {
            String stack = getExceptionStack(throwable);
            String[] logs = stack.split("\r\n\t");
            jobLogsPO.setErrorType(logs[0]);
            StringBuilder errorDetail = new StringBuilder();
            for (String log : logs) {
                if (log.contains("com.blue")) {
                    errorDetail.append(log).append("\n");
                }
            }
            jobLogsPO.setErrorDetail(errorDetail.toString());
            jobLogsPO.setStatus(CommonConstant.FAIL);
            jobLogsService.updateById(jobLogsPO);
        } finally {
            MDC.remove("traceId");
        }
        return null;
    }

    /**
     * 将异常的堆栈信息转成String
     */
    public String getExceptionStack(Throwable throwable) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        throwable.printStackTrace(pw);
        return sw.toString();
    }
}
